package com.example.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.auth.domain.DataNode;
import com.example.config.auth.SecurityUtil;
import com.example.config.exception.GlobalExcetion;
import com.example.config.redis.CacheService;
import com.example.feign.NodeFeignService;
import com.example.system.domain.BusSystemTable;
import com.example.system.domain.BusSystemTableUser;
import com.example.system.domain.PageData;
import com.example.system.mapper.BaseMapperPlus;
import com.example.system.mapper.BusSystemTableUserMapper;
import com.example.system.service.BusSystemTableService;
import com.example.system.service.BusSystemTableUserService;
import com.example.util.ReflectionUtils;
import com.example.util.TotalBasedRoundRobinAllocator;
import com.example.util.sql.DBSql;
import com.example.util.sql.SqlGenerator;
import com.example.util.sql.SqlResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* @author CETC
* @description 针对表【bus_system_table_user】的数据库操作Service实现
* @createDate 2025-10-25 13:12:44
*/
@Service
public class BusSystemTableUserServiceImpl extends ServiceImpl<BusSystemTableUserMapper, BusSystemTableUser>
    implements BusSystemTableUserService{

    @Autowired
    private DataSource dataSource;

    @Value("${spring.application.name}")
    private String appName;

    @Autowired
    private CacheService cacheService;

    @Autowired
    private NodeFeignService nodeFeignService;

    @Autowired
    private BusSystemTableService tableService;

    @Autowired
    private BaseMapperPlus baseMapperPlus;

    @Override
    public BusSystemTableUser selectByUserId(String userId, String tableName) throws GlobalExcetion {
        if(cacheService.containsKey(this.appName+"selectByUserId",userId+"_"+tableName)){
            return cacheService.get(this.appName+"selectByUserId",userId+"_"+tableName,BusSystemTableUser.class);
        }else {
            LambdaQueryWrapper<BusSystemTableUser> lambdaQueryWrapper=new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(BusSystemTableUser::getUserid, userId);
            lambdaQueryWrapper.eq(BusSystemTableUser::getTableName, tableName);
            BusSystemTableUser user=this.getOne(lambdaQueryWrapper);
            if(user!=null){
                cacheService.put(this.appName+"selectByUserId",userId+"_"+tableName,user);
                return user;
            }
            DataNode dataNode =nodeFeignService.getDataNodeConfigByServerName(appName);
            List<BusSystemTable> list=tableService.getListByTableName(tableName);
            if(list==null){
                throw new GlobalExcetion(1,tableName+"不存在");
            }
            Integer total=this.getTotal();
            TotalBasedRoundRobinAllocator<BusSystemTable> base=new TotalBasedRoundRobinAllocator(list);
            BusSystemTable busSystemTable=base.allocateNodeByTotal(total);
            user=new BusSystemTableUser();
            user.setIsDeleted(0);
            user.setNodeId(dataNode.getId());
            user.setTableName(tableName);
            user.setTableNo(busSystemTable.getTableNo());
            user.setTableNode(busSystemTable.getTableNode());
            user.setUserid(userId);
            this.save(user);
            cacheService.put(this.appName+"selectByUserId",userId+"_"+tableName,user);
            return user;
        }
    }

    @Override
    public <T> BusSystemTableUser selectByUserId(String userId, Class<T> cls) throws GlobalExcetion {
        TableName tableName=ReflectionUtils.getClassAnnotation(cls,TableName.class);
        if(tableName==null){
            throw new GlobalExcetion(1,"@TableName 未配置");
        }
        return selectByUserId(userId,tableName.value());
    }


    @Override
    public Integer getTotal() {
        return this.count();
    }

    @Override
    public <T> T saveObjectData(T t) throws GlobalExcetion {
        this.fieldValited(t);
        String userId=(String)ReflectionUtils.getFieldValue(t,"userId");
        if(userId==null || "".equals(userId)){
            throw new GlobalExcetion(1,"用户id数据为空");
        }
        DBSql dbSql=new DBSql(dataSource);
        TableName tableName=ReflectionUtils.getClassAnnotation(t.getClass(),TableName.class);
        BusSystemTableUser busSystemTableUser=this.selectByUserId(userId,tableName.value());
        if(busSystemTableUser==null){
            throw new GlobalExcetion(1,"未配置表数据");
        }
        DataNode dataNode=nodeFeignService.getDataNodeConfigByServerName(appName);
        if(dataNode==null){
            throw new GlobalExcetion(1,"存在数据节点获取不到");
        }
        String saveTable=busSystemTableUser.getSaveTableName();
        String uuid=tableService.createUUID(saveTable);
        ReflectionUtils.setFieldValue(t,"uuid",uuid);
        ReflectionUtils.setFieldValue(t,"updateTime",new Date());
        ReflectionUtils.setFieldValue(t,"createTime",new Date());
        ReflectionUtils.setFieldValue(t,"isDeleted",0);
        ReflectionUtils.setFieldValue(t,"dsNo",dataNode.getId());
        SqlResult sqlResult= SqlGenerator.generateInsert(saveTable,t);
        dbSql.executeInsert(sqlResult.getSql(),sqlResult.getParams().toArray());
        return t;
    }

    @Override
    public <T> T updateObjectDataByUUID(T t) throws GlobalExcetion {
        this.fieldValited(t);
        DBSql dbSql=new DBSql(dataSource);
        String uuid=(String) ReflectionUtils.getFieldValue(t,"uuid");
        ReflectionUtils.setFieldValue(t,"updateTime",new Date());
        String tableName=tableService.getTableNameByUUID(uuid);
        SqlResult sqlResult=SqlGenerator.generateUpdateById(tableName,t,"uuid");
        dbSql.executeUpdate(sqlResult.getSql(),sqlResult.getParams().toArray());
        return t;
    }

    @Override
    public <T> T getObjectDataByUUID(String uuid,Class<T> cls) throws GlobalExcetion {
        String tableName=tableService.getTableNameByUUID(uuid);
        Map map= baseMapperPlus.getDataByUUID(tableName,uuid);
        return JSONObject.parseObject(JSONObject.toJSONString(map),cls);
    }

    @Override
    public boolean deleteDataByUUID(String uuid) throws GlobalExcetion {
        String tableName=tableService.getTableNameByUUID(uuid);
        int code= this.baseMapper.deleteDataByUUID(tableName,uuid);
        return code > 0;
    }

    @Override
    public <T> PageData<T> getPage(Page page, String uid, Class<T> cls) throws GlobalExcetion {
        TableName tableName=ReflectionUtils.getClassAnnotation(cls,TableName.class);
        BusSystemTableUser busSystemTableUser=this.selectByUserId(uid,tableName.value());
        if(busSystemTableUser==null){
            throw new GlobalExcetion(1,"表数据配置存在问题");
        }
        String unionAllTable=busSystemTableUser.generateUnionAllTableUserId();
        IPage<Map> iPage=baseMapperPlus.pageData(unionAllTable,uid,page);
        return pageToPageData(iPage,cls);
    }

    @Override
    public <T> PageData<T> getPage(Page page, String uid, Map<String, Object> params,Class<T> cls) throws GlobalExcetion {
        TableName tableName=ReflectionUtils.getClassAnnotation(cls,TableName.class);
        BusSystemTableUser busSystemTableUser=this.selectByUserId(uid,tableName.value());
        if(busSystemTableUser==null){
            throw new GlobalExcetion(1,"表数据配置存在问题");
        }
        String unionAllTable=busSystemTableUser.generateUnionAllTableUserId();
        IPage<Map> iPage=baseMapperPlus.pageData(unionAllTable,uid,params,page);
        return pageToPageData(iPage,cls);
    }


    /**
     * uuid 主键id,   uuid,user_id,is_deleted, create_time,update_time
     * createTime 创建时间,
     * updateTime  更新时间,
     * isDeleted  是否删除,
     * userId    用户所属数据id
     * @param t
     * @param <T>
     * @throws GlobalExcetion
     */
    public <T> void fieldValited(T t) throws GlobalExcetion {
        TableName tableName=ReflectionUtils.getClassAnnotation(t.getClass(), TableName.class);
        if(tableName==null ){
            throw new GlobalExcetion(1,"未配置@TableName注解");
        }
        boolean isHasField=ReflectionUtils.hasAllFields(t,"uuid","createTime","updateTime","isDeleted","userId","dsNo");
        if(!isHasField){
            throw new GlobalExcetion(1,"uuid,createTime,updateTime,isDeleted,userId,dsNo 有字段不存在");
        }
    }

    private <T> PageData<T> pageToPageData(IPage<Map> iPage,Class<T> cls)  {
        PageData<T> pageData=new PageData<>();
        pageData.setTotal(iPage.getTotal());
        if(iPage.getRecords()!=null){
            List<T> tList=new ArrayList<T>();
            for(Map map:iPage.getRecords()){
                T t=JSONObject.parseObject(JSONObject.toJSONString(map),cls);
                tList.add(t);
            }
            pageData.settList(tList);
        }
        return pageData;
    }
}




